JvnCoordImpl.java

Go to the documentation of this file.
00001 
00009 package jvn;
00010 
00011 import java.rmi.Naming;
00012 import java.rmi.RemoteException;
00013 import java.rmi.server.UnicastRemoteObject;
00014 import java.util.HashMap;
00015 import java.util.Iterator;
00016 import java.util.LinkedList;
00017 import java.util.concurrent.Semaphore;
00018 import java.io.IOException;
00019 import java.io.Serializable;
00020 
00027 class JvnInvalidateReaderThread extends Thread
00028 {
00032         private int objectID;
00033 
00039         private Semaphore semaphore;
00040 
00045         private JvnRemoteServer server;
00046 
00056         JvnInvalidateReaderThread( Semaphore sema, JvnRemoteServer serv, int joi )
00057         {
00058                 server = serv;
00059                 objectID = joi;
00060                 semaphore = sema;
00061         }
00062 
00068         public void run() {
00069                 try {
00070                         server.jvnInvalidateReader(objectID);
00071                 } catch(JvnException e) {
00072                         System.out.println("Javanaise error while invalidating reader: " + e);
00073                 }
00074                 catch(RemoteException e) {
00075                         System.out.println("Network error while invalidating reader: " + e);
00076                 }
00077 
00078                 semaphore.release();
00079         }
00080 }
00081 
00086 class JvnServers {
00091         public JvnServers(JvnRemoteServer server, JvnObject obj) throws JvnException
00092         {
00093                 jvnListOfServers.add(server);
00094                 jvnObject = obj;
00095                 if( obj!=null ) {
00096                         try {
00097                                 latestJvnObjectContent = obj.jvnGetObjectState();
00098                         } catch( JvnException e ) {
00099                                 latestJvnObjectContent = null;
00100                         }
00101                 }
00102         }
00103 
00108         public LinkedList<JvnRemoteServer> jvnListOfServers = new LinkedList<JvnRemoteServer>();
00109 
00113         public JvnObject jvnObject = null;
00114 
00120         public JvnObjectState lockState = null;
00121 
00125         public Serializable latestJvnObjectContent = null;
00126 }
00127 
00132 public class JvnCoordImpl extends UnicastRemoteObject implements JvnRemoteCoord {
00136         private static final long serialVersionUID = -115305878534728396L;
00137 
00144         private int currID = -1;
00145 
00149         private static JvnCoordImpl jo = null;
00150 
00155         private HashMap<String,JvnServers> jvnServersOfNames = new HashMap<String, JvnServers>();
00156 
00163         private HashMap<Integer,JvnServers> jvnServersOfIdentifiers = new HashMap<Integer, JvnServers>();
00164 
00168         private JvnCoordImpl() throws Exception {
00169                 Naming.rebind("AT_LD_jvnCoordinator", this);
00170                 System.out.println("Javanaise Coordinator is ready.");
00171                 currID = 0;
00172         }
00173 
00180         public static void main(String argv[]) throws Exception {
00181                 if(jo==null){
00182                         jo = new JvnCoordImpl();
00183                         System.out.println("Press ENTER to terminate the Javanaise Coordinator.");
00184                         try {
00185                                 System.in.read();
00186                         } catch (IOException e) {}
00187                 }
00188         }
00189 
00193         public int jvnGetObjectId()
00194         throws java.rmi.RemoteException,jvn.JvnException {
00195                 synchronized(this) {
00196                         return (++currID);
00197                 }
00198         }
00199 
00209         public void jvnRegisterObject(String jon, JvnObject jo, JvnRemoteServer js)
00210         throws java.rmi.RemoteException,jvn.JvnException{
00211                 // No one synchronizes on jvnServersOfNames,
00212                 // synchronize on jvnServersOfIdentifiers
00213                 synchronized(jvnServersOfIdentifiers) {
00214 
00215                         // Verify stuff
00216                         if( jo==null ) {
00217                                 throw new JvnException("Invalid object!");
00218                         } else if( jo.jvnGetObjectId() < 0 ) {
00219                                 throw new JvnException( "Invalid object ID! Please call jvnGetObjectId " +
00220                                                                                 "to get a new object ID and associate it with the " +
00221                                                                                 "Javanaise object using the jvnSetObjectId method." );
00222                         } else if( jvnServersOfIdentifiers.containsKey(jo.jvnGetObjectId()) ) {
00223                                 throw new JvnException("Object with such an ID is already registered with this coordinator!");
00224                         } else if( jvnServersOfNames.containsKey(jon) ) {
00225                                 throw new JvnException("Object with such a name is already registered with this coordinator!");
00226                         }
00227 
00228                         System.out.println("Registering object \""+jon+"\" (Object ID: "+jo.jvnGetObjectId()+")");
00229 
00230                         // All verifications are done, add to lists.
00231                         JvnServers servers = new JvnServers(js,jo);
00232                         servers.lockState = JvnObjectState.STATE_WLOCKT;
00233                         jvnServersOfNames.put(jon, servers);
00234                         jvnServersOfIdentifiers.put(jo.jvnGetObjectId(), servers);
00235                 }
00236         }
00237 
00247         public JvnObject jvnLookupObject(String jon, Class<? extends JvnObject> type, JvnRemoteServer js)
00248         throws java.rmi.RemoteException,jvn.JvnException{
00249                 // Verify arguments
00250                 if( js==null ) {
00251                         throw new JvnException( "Invalid server! When calling this method " +
00252                                                                         "from a JvnRemoteServer, set the second "+
00253                                                                         "argument to \"this\".");
00254                 }
00255 
00256                 System.out.println("Looked up object: "+jon);
00257 
00258                 // No one synchronizes on jvnServersOfNames,
00259                 // synchronize on jvnServersOfIdentifiers
00260                 synchronized(jvnServersOfIdentifiers) {
00261                         JvnServers servers = jvnServersOfNames.get(jon);
00262                         if( servers != null ) {
00263                                 System.out.println("Found object with name \"" + jon + "\"");
00264                                 return servers.jvnObject;
00265                         } else {
00266                                 System.out.println("Not found object with name \"" + jon + "\"");
00267                                 return null;
00268                         }
00269                 }
00270         }
00271 
00280         public Serializable jvnLockRead(int joi, JvnRemoteServer js)
00281         throws java.rmi.RemoteException, JvnException{
00282                 // Verify arguments
00283                 if( js==null ) {
00284                         throw new JvnException( "Invalid server! When calling this method " +
00285                                                                         "from a JvnRemoteServer, set the second "+
00286                                                                         "argument to \"this\".");
00287                 }
00288 
00289                 synchronized(jvnServersOfIdentifiers)
00290                 {
00291                         JvnServers servers = jvnServersOfIdentifiers.get(joi);
00292                         if( servers == null ) {
00293                                 throw new JvnException( "The given object identifier is not registered" +
00294                                 "with this coordinator!" );
00295                         } else if( servers.lockState == JvnObjectState.STATE_NOLOCK ) {
00296                                 // No lock, just read lock and set the only reference
00297                                 System.out.println("Read lock: getting lock (was not locked before).");
00298                                 servers.lockState = JvnObjectState.STATE_RLOCKT;
00299                                 servers.jvnListOfServers.clear();
00300                                 servers.jvnListOfServers.add(js);
00301                         } else if( servers.lockState == JvnObjectState.STATE_RLOCKT ) {
00302                                 // Read lock, just add a reference
00303                                 System.out.println("Read lock: adding reference.");
00304                                 servers.jvnListOfServers.add(js);
00305                         } else if( servers.lockState == JvnObjectState.STATE_WLOCKT ) {
00306                                 try {
00307                                         System.out.println("Read lock: invalidating writer for reader.");
00308                                         JvnRemoteServer server = servers.jvnListOfServers.iterator().next();
00309                                         servers.latestJvnObjectContent = server.jvnInvalidateWriterForReader(joi);
00310                                         servers.lockState = JvnObjectState.STATE_RLOCKT;
00311                                         if( server.equals(js)) {
00312                                                 System.out.println("Read lock: downgraded from write lock.");
00313                                         } else {
00314                                                 System.out.println("Read lock: adding reference.");
00315                                                 servers.jvnListOfServers.add(js);
00316                                         }
00317                                 } catch( Exception e ) {
00318                                         // This will catch all kinds of stuff, including null pointers
00319                                         throw new JvnException("Error getting the read lock!\n"+e);
00320                                 }
00321                         } else {
00322                                 throw new JvnException("Unexpected lock state: " + servers.lockState + " !\n");
00323                         }
00324 
00325                         return servers.latestJvnObjectContent;
00326                 }
00327         }
00328 
00337         public Serializable jvnLockWrite(int joi, JvnRemoteServer js)
00338         throws java.rmi.RemoteException, JvnException{
00339                 // Verify arguments
00340                 if( js==null ) {
00341                         throw new JvnException( "Invalid server! When calling this method " +
00342                                                                         "from a JvnRemoteServer, set the second "+
00343                                                                         "argument to \"this\".");
00344                 }
00345 
00346                 synchronized(jvnServersOfIdentifiers)
00347                 {
00348                         JvnServers servers = jvnServersOfIdentifiers.get(joi);
00349                         if( servers == null ) {
00350                                 throw new JvnException( "The given object identifier is not registered" +
00351                                                                                 "with this coordinator!" );
00352                         } else if( servers.lockState == JvnObjectState.STATE_NOLOCK ) {
00353                                 // No lock, just read lock
00354                                 System.out.println("Write lock: getting lock (was not locked before).");
00355                                 servers.lockState = JvnObjectState.STATE_WLOCKT;
00356                         } else if( servers.lockState == JvnObjectState.STATE_RLOCKT ) {
00357                                 System.out.println("Write lock: invalidating readers.");
00358                                 // Get back the read lock from all servers
00359                                 int numberOfReaders = 0;
00360                                 Semaphore s = new Semaphore(0);
00361 
00362                                 Iterator<JvnRemoteServer> i = servers.jvnListOfServers.iterator();
00363                                 while(i.hasNext()) {
00364                                         numberOfReaders++;
00365                                         (new JvnInvalidateReaderThread(s,i.next(),joi)).start();
00366                                 }
00367 
00368                                 // Wait for all threads to end
00369                                 if( numberOfReaders>0 ) {
00370                                         try {
00371                                                 s.acquire(numberOfReaders);
00372                                         } catch (InterruptedException e) {}
00373                                 }
00374                                 System.out.println("Write lock: invalidated "+numberOfReaders+" readers.");
00375                         } else if( servers.lockState == JvnObjectState.STATE_WLOCKT ) {
00376                                 try {
00377                                         // Write-locked, request object
00378                                         System.out.println("Write lock: invalidating writer.");
00379                                         servers.latestJvnObjectContent = servers.jvnListOfServers.iterator().next().jvnInvalidateWriter(joi);
00380                                         System.out.println("Write lock: invalidated writer.");
00381                                 } catch( Exception e ) {
00382                                         throw new JvnException("Error getting the write lock!\n"+e);
00383                                 }
00384                         } else {
00385                                 throw new JvnException("Unexpected lock state: "+servers.lockState+" !\n");
00386                         }
00387 
00388                         servers.jvnListOfServers.clear();
00389                         servers.jvnListOfServers.add(js);
00390                         servers.lockState = JvnObjectState.STATE_WLOCKT;
00391 
00392                         return servers.latestJvnObjectContent;
00393                 }
00394         }
00395 
00402         public void jvnServerTerminated(JvnRemoteServer js) throws RemoteException, JvnException {
00403                 // All verifications are done, add to lists.
00404                 // No one synchronizes on jvnServersOfNames,
00405                 // synchronize on jvnServersOfIdentifiers
00406                 System.out.println("A server has terminated: unregistering.");
00407 
00408                 synchronized(jvnServersOfIdentifiers) {
00409                         Iterator<JvnServers> i = jvnServersOfIdentifiers.values().iterator();
00410                         Iterator<JvnRemoteServer> j = null;
00411                         JvnRemoteServer server = null;
00412                         JvnServers servers = null;
00413 
00414                         // Loop on the list of registered objects
00415                         while(i.hasNext()) {
00416                                 servers = i.next();
00417                                 j = servers.jvnListOfServers.iterator();
00418 
00419                                 // Loop on the list of servers
00420                                 while(j.hasNext()) {
00421                                         server = j.next();
00422 
00423                                         // Server found! Invalidate...
00424                                         if(server.equals(js)) {
00425                                                 if(servers.lockState == JvnObjectState.STATE_WLOCKT) {
00426                                                         System.out.println("A server has terminated: invalidating writer.");
00427                                                         servers.latestJvnObjectContent = servers.jvnObject.jvnInvalidateWriter();
00428                                                 }
00429                                                 servers.jvnListOfServers.remove(server);
00430                                                 if(servers.jvnListOfServers.isEmpty()) {
00431                                                         servers.lockState = JvnObjectState.STATE_NOLOCK;
00432                                                 }
00433                                                 break;
00434                                         }
00435                                 }
00436                         }
00437                 }
00438                 System.out.println("A server has terminated: unregister complete.");
00439         }
00440 }

Generated on Wed Jan 2 10:15:54 2008 for Javanaise by  doxygen 1.5.4